
/**
 * Date:2019年5月30日下午4:35:47
 * Copyright (c) 2019, www.bwbroad.com All Rights Reserved.
 *
*/

package com.xue.im.server.handler;

import java.net.InetAddress;
import java.net.InetSocketAddress;

import com.xue.im.common.IMUtil;
import com.xue.im.common.IMUtil.MessageType;
import com.xue.im.common.vo.Message;
import com.xue.im.server.core.IMServerContext;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.ipfilter.IpFilterRule;
import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;

/**
 * Description: 服务器端业务处理 <br/>
 * Date: 2019年5月30日 下午4:35:47 <br/>
 * 
 * @author xuejianxin
 */
@Sharable
public class TextResponseHandler extends ChannelInboundHandlerAdapter {

	// 读取数据
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		Message message = (Message) msg;
		if (message.getHeader().getLength() <= IMUtil.MESSAGE_LEN) {
			if (IMUtil.checkMessageType(message, MessageType.TEXT_REQ)) {
				dispachMessage(ctx, message, MessageType.TEXT_RESP);
			} else if (IMUtil.checkMessageType(message, MessageType.FILE_REQ)) {
				dispachMessage(ctx, message, MessageType.FILE_RESP);
			} else {
				ctx.fireChannelRead(msg);
			}
		}
	}

	// 转发信息
	private void dispachMessage(ChannelHandlerContext ctx, Message message, MessageType respType) {
		// 获取接收人
		String receiver = (String) message.getOption(IMUtil.RECEIVER);
		// 修改消息类型为TEXT_RESP
		message.getHeader().setType(respType.value());
		// 转发
		IMServerContext.getUserCtx(receiver).filter(to -> {
			return isAllow(ctx, to);
		}).ifPresent(receiverCtx -> receiverCtx.writeAndFlush(message));
	}

	private static boolean isAllow(InetAddress from, InetAddress to) {
		boolean success = false;
		try {
			InetAddress net13 = InetAddress.getByName("172.16.13.0");
			// 允许172.16.13.0 网段内互相发送信息
			// 不允许172.16.13.0 往其他网段发送信息
			IpFilterRule ru13 = new IpSubnetFilterRule(net13, 24, IpFilterRuleType.ACCEPT);
			if (ru13.matches(new InetSocketAddress(from.getHostAddress(), 0))) {// 如果是13网段发出
				if (ru13.matches(new InetSocketAddress(to.getHostAddress(), 0))) {// 13网段接收
					success = true;
				}
			} else {// 如果不是13网段发出则都放过
				success = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.printf("**from %s to %s ,success=%s\r\n", from.getHostAddress(), to.getHostAddress(), success);
		return success;
	}

	private static boolean isAllow(ChannelHandlerContext from, ChannelHandlerContext to) {
		if (null == from || null == to) {
			return false;
		}
		InetAddress fromIp = ((InetSocketAddress) from.channel().remoteAddress()).getAddress();
		InetAddress toIp = ((InetSocketAddress) to.channel().remoteAddress()).getAddress();
		return isAllow(fromIp, toIp);
	}

	public static void main(String[] args) throws Exception {
		// cidr 参数参考 https://blog.csdn.net/yaoyao4959/article/details/10084973
		// 子网掩码为16位
		// IpFilterRule r = new IpSubnetFilterRule(InetAddress.getByName("192.168.1.5"),
		// 16, IpFilterRuleType.ACCEPT);
		// 相同子网验证通过
		// boolean isOk = r.matches(new InetSocketAddress("192.168.1.4", 8080));
		// System.out.println(isOk);
		// 子网不同验证不通过
		// isOk = r.matches(new InetSocketAddress("192.167.1.5", 8080));
		// System.out.println(isOk);
		// isOk = r.matches(new InetSocketAddress("192.168.3.5", 8080));
		// System.out.println(isOk);

		System.out.println(isAllow(InetAddress.getByName("172.16.13.56"), InetAddress.getByName("172.16.13.205")));
		System.out.println(isAllow(InetAddress.getByName("172.16.13.56"), InetAddress.getByName("172.16.12.205")));
		System.out.println(isAllow(InetAddress.getByName("192.168.1.168"), InetAddress.getByName("172.16.13.205")));
	}

}
